package ink.tiptop.common.worker.scan;

import ink.tiptop.utils.async.executor.Async;
import ink.tiptop.utils.async.wrapper.WorkerWrapper;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author ink.tiptop.zjf
 * @Title: Ticket
 * @Package ink.tiptop.service.impl
 * @Description: 通用的本地扫描器, 调用worker异步执行
 * 调用 {@link ScanWorker#action(String, Map)} 执行
 * @date 2020-07-24 14:16
 */
@Getter
@Setter
@Slf4j
public class LocalScanner {

    /**
     * 在扫描本地的包下的时候,必须用 深度必须用2
     * 防止扫描到lib下面的依赖,会导致数据会非常多
     */
    private static final int DEFAULT_DEEP = 5;
    /**
     * 最大搜索深度
     * 比如 深度为3
     */
    private Integer deep;

    private boolean underTarget;
    /**
     * 本地搜索起始路径
     * 比如 入参为/Users/zhongjiafeng/Desktop/OSChina/Ticket/boot-web-webwork 深度为0
     */
    private List<String> localPathList = new ArrayList<>();

    public LocalScanner(String localPath) {
        this.localPathList.add(localPath);
        this.deep = DEFAULT_DEEP;
    }

    public LocalScanner(List<String> localPathList) {
        this.localPathList.addAll(localPathList);
        this.deep = DEFAULT_DEEP;
    }
    public LocalScanner(List<String> localPathList,boolean underTarget) {
        this.localPathList.addAll(localPathList);
        this.deep = DEFAULT_DEEP;
        this.underTarget = underTarget;
    }

    public LocalScanner(String localPath, Integer deep) {
        this.localPathList.add(localPath);
        this.deep = deep;
    }
    public LocalScanner(List<String> localPathList, Integer deep) {
        this.localPathList.addAll(localPathList);
        this.deep = deep;
    }

    /**
     * 这里为什么不把filePattern当做构造参数?
     * 因为filePattern是可以变换的,构造参数中的路径和深度可以不变
     *
     * @param filePattern
     * @return
     */
    public List<String> scan(String filePattern) {
        List<String> resultList = new ArrayList<>();
        Pattern compile = Pattern.compile(filePattern);
        // 这里给倒计层数赋值,让当前的方法可以使用多次
        // 封装成一个异步的执行对象
        for (String localPath : localPathList) {
            ScanWorker sw = new ScanWorker(localPath, compile, deep);
            WorkerWrapper<String, ScanResult> workerWrapper = new WorkerWrapper.Builder<String, ScanResult>()
                    .worker(sw)
                    .callback(sw)
                    .param("0")
                    .build();
            try {
                // 执行异步请求
                Async.beginWork(3000, workerWrapper);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return new ArrayList<>();
            }
            ScanResult result = workerWrapper.getWorkResult().getResult();
            resultList.addAll(result.getPathList());
        }
        return resultList;
    }
}
